﻿using CfgTable;
using IQIGame.Onigao.Framework;
using NetProtocol.Enum;
using NetProtocol.POD;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// 进行中的任务
    /// </summary>
    public class QuestData : IReusableClass
    {
        /// <summary>
        /// 配置id
        /// </summary>
        public int cid { get; private set; }
        /// <summary>
        /// 进度
        /// </summary>
        public int progress { get; private set; }
        /// <summary>
        /// 创建时间
        /// </summary>
        public long createTime { get; private set; }

        /// <summary>
        /// 任务的状态
        /// </summary>
        public QuestStatus status;
        /// <summary>
        /// 父任务id
        /// </summary>
        public int parentCid;
        /// <summary>
        /// 已领奖阶段，当前阶段可根据progress匹配
        /// </summary>
        public int rewardPhase;

        public CfgQuest cfgData => TableCenter.quest.Get(cid);

        /// <summary>
        /// 是否可提交
        /// </summary>
        public bool isCanCommit => cfgData != null && cfgData.TargetNum <= this.progress;

        public QuestData Sync(QuestPOD pod)
        {
            this.cid = pod.cid;
            this.progress = pod.progress;
            this.createTime = pod.createTime;
            this.status = pod.status;
            this.parentCid = pod.parentCid;
            this.rewardPhase = pod.rewardPhase;
            return this;
        }

        public void Clear()
        {
            this.cid = 0;
            this.progress = 0;
            this.createTime = 0;
            this.status = QuestStatus.Accepted;
            this.parentCid = 0;
            this.rewardPhase = 0;
        }

        #region 对象池
        public uint MaxStore => 20;

        public void OnReset()
        {
            this.Clear();
        }

        public void Put2Pool()
        {
            ClassPool.Put(this);
        }

        static public QuestData NewFromPool()
        {
            return ClassPool.Get<QuestData>();
        }
        #endregion

        static public QuestData ConvertFromPOD(QuestPOD pod)
        {
            if (pod == null)
                return null;
            QuestData ret = NewFromPool().Sync(pod);
            return ret;
        }
    }

    public class QuestModuleData
    {
        private List<int> currentQuestKeys;
        private Dictionary<int, QuestData> currentQuests; // 进行中
        private HashSet<int> committedQuests; // 已完成 - 成功了的
        private HashSet<int> failedQuests; // 已完成 - 失败了的

        public int trackQuestCid { get; private set; } //当前跟踪的任务
        public CfgQuest trackQuestCfg => trackQuestCid <= 0 ? null : TableCenter.quest.Get(trackQuestCid);

        public IReadOnlyList<int> keyInProgress => currentQuestKeys;
        public IReadOnlyList<int> keyInSuccess => committedQuests.ToList();

        public QuestModuleData(List<QuestPOD> quests, List<int> committedQuestList, List<int> failQuestList, int trackQuestCid)
        {
            this.currentQuestKeys = new();
            this.currentQuests = new();
            this.committedQuests = new();
            this.failedQuests = new();
            this.trackQuestCid = trackQuestCid;

            foreach (QuestPOD pod in quests)
            {
                if (currentQuests.ContainsKey(pod.cid))
                {
                    LogGame.LogError($"Has same Quest , cid = {pod.cid}");
                }
                else
                {
                    Add(QuestData.ConvertFromPOD(pod));
                }
            }

            foreach (int cid in committedQuestList)
            {
                this.committedQuests.Add(cid);
            }

            foreach (int cid in failQuestList)
            {
                this.failedQuests.Add(cid);
            }
        }

        public void UpdateTrackQuest(int cid)
        {
            trackQuestCid = cid;
        }

        public bool ContainsKey(int cid)
        {
            return currentQuests.ContainsKey(cid);
        }

        public bool TryGetValue(int cid, out QuestData result)
        {
            return currentQuests.TryGetValue(cid, out result);
        }

        public void Add(QuestData data)
        {
            currentQuestKeys.Add(data.cid);
            currentQuests[data.cid] = data;
        }

        public bool Remove(int cid)
        {
            currentQuestKeys.Remove(cid);
            return currentQuests.Remove(cid);
        }

        public bool IsInSuccess(int cid)
        {
            return committedQuests.Contains(cid) && !ContainsKey(cid);
        }

        public bool IsInFail(int cid)
        {
            return failedQuests.Contains(cid) && !ContainsKey(cid);
        }

        public void AddSuccess(int cid)
        {
            committedQuests.Add(cid);
        }

        public void RemoveSuccess(int cid)
        {
            committedQuests.Remove(cid);
        }

        public void AddFail(int cid)
        {
            failedQuests.Add(cid);
        }

        public void RemoveFail(int cid)
        {
            failedQuests.Remove(cid);
        }

        public void Clear()
        {
            foreach (var item in this.currentQuests.Values)
            {
                item.Put2Pool();
            }
            this.currentQuestKeys.Clear();
            this.currentQuests.Clear();
            this.committedQuests.Clear();
            this.failedQuests.Clear();
        }
    }
}
